﻿///////////////////////////////////////////////////////////////////////////////
// File Name: SkinButton.cpp
// Author: 张东斌、ChongyangLee, lynnux
// E_Mail: malutianshi7905@sina.com; ChongyangLee@hotmail.com; lynnux@yeah.net
// History: 
// 2009/11/18 Fix 没有释放的DC句柄
// 2009/09/26 Fix 根据 按钮皮肤名 加载 按钮皮肤
// 2009/09/26 Add 根据 ID 加载按钮皮肤
// 2009/09/26 Fix 按钮的鼠标行为
// 
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "skinbutton.h"
#include "ButtonSkin.h"
#include "RadioSkin.h"
#include "CheckBoxSkin.h"
#include "GroupBoxSkin.h"


const char* CSkinButton::DEFNAME = _T("Button");

CSkinButton::CSkinButton( void ): m_CaptureState(NO_CAPTURE_OR_UP_RELEASE)
{
	//m_pButtonSkin = NULL;//GetSkin().GetButtonSkin();
	//m_pCheckSkin = GetSkin().GetCheckBoxSkin();
	//m_pRadioSkin = GetSkin().GetRadioSkin();
	//m_pGroupSkin = GetSkin().GetGroupBoxSkin();
	//m_nButtonType = BTNTYPE_PUSHBUTTON;
	//m_nButtonState = BUTTON_NORMAL;
}

CSkinButton::~CSkinButton(void)
{
	HookWindow((HWND)NULL);
}
BOOL CSkinButton::LoadSkin(const char* pszName)
{
    CAutoEnableSkin a(m_bEnableSkin);
    BOOL bRet = FALSE;
    if (BTNTYPE_PUSHBUTTON == m_nButtonType)
    {
        m_pButtonSkin = GetSkin().GetButtonSkin(m_nID); // 先尝试加载ID皮肤
        if(!m_pButtonSkin)
        {
            m_pButtonSkin = GetSkin().GetButtonSkin(pszName);
        }
        bRet = (BOOL)m_pButtonSkin;
    }
    else if (BTNTYPE_CHECKBOX == m_nButtonType)
    {
        m_pCheckSkin = GetSkin().GetCheckBoxSkin();
        bRet = (BOOL)m_pCheckSkin;
    }
    else if (BTNTYPE_RADIOBOX == m_nButtonType)
    {
        m_pRadioSkin = GetSkin().GetRadioSkin();
        bRet = (BOOL)m_pRadioSkin;
    }
    else if (BTNTYPE_GROUPBOX == m_nButtonType)
    {
        m_pGroupSkin = GetSkin().GetGroupBoxSkin();
        bRet = (BOOL)m_pGroupSkin;
    }
	//SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 
    return bRet;
}
BOOL CSkinButton::InstallSkin(HWND hWnd)
{
	if(!hWnd)
		return FALSE;
    m_nID = ::GetDlgCtrlID(hWnd);

    // 获取窗口类型
#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(hWnd, GWL_STYLE);
	LONG_PTR exstyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
#else
	DWORD style     = GetWindowLong( hWnd, GWL_STYLE );
	DWORD exstyle	= GetWindowLong(hWnd,GWL_EXSTYLE);
#endif
	if(style & WS_DISABLED)
	{
		SetState(m_nButtonState, BUTTON_DISABLED);
	}
    m_bIcon = style & BS_ICON;

	switch (style & SS_TYPEMASK)
	{
	case BS_OWNERDRAW:          
		m_nButtonType = BTNTYPE_UNKNOWN;    // 跳过自绘的？
		break;
	case BS_DEFPUSHBUTTON:	
		m_nButtonType = BTNTYPE_PUSHBUTTON;		
		SetState(m_nButtonState, BUTTON_DEFAULT);
		break;
	case BS_PUSHBUTTON:
#ifndef BS_PUSHBOX
#define BS_PUSHBOX          0x0000000AL
#endif
	case BS_PUSHBOX:
		m_nButtonType = BTNTYPE_PUSHBUTTON;
		break;

	case BS_CHECKBOX:			
	case BS_AUTOCHECKBOX:		
	case BS_3STATE:				
	case BS_AUTO3STATE:			
		if (style & BS_PUSHLIKE)
			m_nButtonType = BTNTYPE_PUSHBUTTON;
		else
			m_nButtonType = BTNTYPE_CHECKBOX;
		break;

	case BS_RADIOBUTTON:		
	case BS_AUTORADIOBUTTON:	
		if (style & BS_PUSHLIKE)
			m_nButtonType = BTNTYPE_PUSHBUTTON;
		else
			m_nButtonType = BTNTYPE_RADIOBOX;
		break;
	case BS_GROUPBOX:	
		m_nButtonType = BTNTYPE_GROUPBOX;
		break;
	default:	
		m_nButtonType = BTNTYPE_UNKNOWN;
	}
    if (!LoadSkin())
    {
        return FALSE;
    }
    HookWindow( (HWND)NULL);
    HookWindow( hWnd );
	if(m_nButtonType == BTNTYPE_UNKNOWN)
		m_bEnableSkin = FALSE;
	if(m_nButtonState == BTNTYPE_PUSHBUTTON && m_pButtonSkin == NULL)
		m_bEnableSkin = FALSE;
	
	if(m_nButtonState == BTNTYPE_CHECKBOX && m_pCheckSkin == NULL)
		m_bEnableSkin = FALSE;

	if(m_nButtonState == BTNTYPE_RADIOBOX && m_pRadioSkin == NULL)
		m_bEnableSkin = FALSE;

	if(m_nButtonState == BTNTYPE_GROUPBOX && m_pGroupSkin == NULL)
		m_bEnableSkin = FALSE;

	DWORD dwState = (LONG) SendMessage(hWnd, BM_GETCHECK, 0, 0);
	if ( dwState == BST_CHECKED )
	{
		SetState(m_nButtonState, BUTTON_CHECKED);
	}
	else
	{
		SetState(m_nButtonState, BUTTON_CHECKED, false);
	}

	if ( dwState == BST_INDETERMINATE )
	{
		SetState(m_nButtonState, BUTTON_INDETERMINATE);
	}
	else
	{
		SetState(m_nButtonState, BUTTON_INDETERMINATE, false);
	}
	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 

}
BOOL CSkinButton::InstallSkin(HWND hWnd,CString strSkinName)
{
	if(!hWnd || strSkinName.IsEmpty())
		return FALSE;

	m_bEnableSkin = TRUE;
	HookWindow( (HWND)NULL);

	CObjectSkin* pObjectSkin = GetSkin().FindObjectSkin(strSkinName);
	if(pObjectSkin)
	{
		if(pObjectSkin->GetSkinType() == keButtonSkin)
			m_pButtonSkin = (CButtonSkin*)pObjectSkin;
		else if(pObjectSkin->GetSkinType() == keCheckBoxSkin)
			m_pCheckSkin = (CCheckBoxSkin*)pObjectSkin;
		else if(pObjectSkin->GetSkinType() == keGroupBoxSkin)
			m_pGroupSkin = (CGroupBoxSkin*)pObjectSkin;
		else if(pObjectSkin->GetSkinType() == keRadioSkin)
			m_pRadioSkin = (CRadioSkin*)pObjectSkin;
	}
	if(!m_pButtonSkin)
		m_pButtonSkin = GetSkin().GetButtonSkin();
	if(!m_pCheckSkin)
		m_pCheckSkin = GetSkin().GetCheckBoxSkin();
	if(!m_pRadioSkin)
		m_pRadioSkin = GetSkin().GetRadioSkin();
	if(!m_pGroupSkin)
		m_pGroupSkin = GetSkin().GetGroupBoxSkin();

#ifdef _WIN64
	LONG_PTR style = GetWindowLongPtr(hWnd, GWL_STYLE);
	LONG_PTR exstyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
#else
	DWORD style = GetWindowLong(hWnd, GWL_STYLE);
	DWORD exstyle = GetWindowLong(hWnd, GWL_EXSTYLE);
#endif
	if(style&WS_DISABLED)
	{	
		SetState(m_nButtonState, BUTTON_DISABLED);
	}
	if(style&BS_ICON)
		m_bIcon = TRUE;
	else
		m_bIcon = FALSE;
	switch (style & SS_TYPEMASK)
	{
	case BS_OWNERDRAW:          
		m_nButtonType = BTNTYPE_UNKNOWN;
		break;
	case BS_DEFPUSHBUTTON:	
		m_nButtonType = BTNTYPE_PUSHBUTTON;
		SetState(m_nButtonState, BUTTON_DEFAULT, true);
		break;
	case BS_PUSHBUTTON:
	case BS_PUSHBOX:
		m_nButtonType = BTNTYPE_PUSHBUTTON;
		break;
	case BS_CHECKBOX:			
	case BS_AUTOCHECKBOX:		
	case BS_3STATE:				
	case BS_AUTO3STATE:			
		if (style & BS_PUSHLIKE)
			m_nButtonType = BTNTYPE_PUSHBUTTON;
		else
			m_nButtonType = BTNTYPE_CHECKBOX;
		break;
	case BS_RADIOBUTTON:		
	case BS_AUTORADIOBUTTON:	
		if (style & BS_PUSHLIKE)
			m_nButtonType = BTNTYPE_PUSHBUTTON;
		else
			m_nButtonType = BTNTYPE_RADIOBOX;
		break;
	case BS_GROUPBOX:	
		m_nButtonType = BTNTYPE_GROUPBOX;
		break;
	default:	
		m_nButtonType = BTNTYPE_UNKNOWN;
	}

	if(m_nButtonType == BTNTYPE_UNKNOWN)
		m_bEnableSkin = FALSE;
	if(m_nButtonState == BTNTYPE_PUSHBUTTON && m_pButtonSkin == NULL)
		m_bEnableSkin = FALSE;

	if(m_nButtonState == BTNTYPE_CHECKBOX && m_pCheckSkin == NULL)
		m_bEnableSkin = FALSE;

	if(m_nButtonState == BTNTYPE_RADIOBOX && m_pRadioSkin == NULL)
		m_bEnableSkin = FALSE;

	if(m_nButtonState == BTNTYPE_GROUPBOX && m_pGroupSkin == NULL)
		m_bEnableSkin = FALSE;

	if(!m_bEnableSkin)
		return FALSE;

	int r = HookWindow( hWnd );

	DWORD dwState = (LONG) SendMessage(hWnd, BM_GETCHECK, 0, 0);
	if ( dwState == BST_CHECKED )
	{
		SetState(m_nButtonState, BUTTON_CHECKED, true);
	}
	else
	{
		SetState(m_nButtonState, BUTTON_CHECKED, false);
	}

	if ( dwState == BST_INDETERMINATE )
	{
		SetState(m_nButtonState, BUTTON_INDETERMINATE, true);
	}
	else
	{
		SetState(m_nButtonState, BUTTON_INDETERMINATE, false);
	}

	SetWindowPos(m_hWnd,NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); 

}
UINT CSkinButton::ButtonStyle2Format(DWORD style)
{
	UINT dtStyle = DT_NOCLIP;  /* We use SelectClipRgn to limit output */

	if (style & BS_PUSHLIKE)
		style &= ~0x0F;

	if (!(style & BS_MULTILINE))
		dtStyle |= DT_SINGLELINE;
	else
		dtStyle |= DT_WORDBREAK;

	switch (style & BS_CENTER)
	{
	case BS_LEFT:   /* DT_LEFT is 0 */    break;
	case BS_RIGHT:  dtStyle |= DT_RIGHT;  break;
	case BS_CENTER: dtStyle |= DT_CENTER; break;
	default:
	
		if (m_nButtonType == BTNTYPE_PUSHBUTTON) dtStyle |= DT_CENTER;
	}

	if (m_nButtonType!= BTNTYPE_GROUPBOX)
	{
		switch (style & BS_VCENTER)
		{
		case BS_TOP:     /* DT_TOP is 0 */      break;
		case BS_BOTTOM:  dtStyle |= DT_BOTTOM;  break;
		case BS_VCENTER: /* fall through */
		default:         dtStyle |= DT_VCENTER; break;
		}
	}
	else
		dtStyle |= DT_SINGLELINE;

	return dtStyle;
}
LRESULT CSkinButton::OnWndMsg(UINT msg,WPARAM wp,LPARAM lp)
{
	switch(msg)
	{
	case BM_SETSTATE:
		OnBMSetState(wp,lp);
		return 0;
	case BM_SETSTYLE:
		OnBMSetStyle(wp,lp);
		return 0;
	case BM_SETCHECK:
		OnBMSetCheck(wp,lp);
		return 0;
	case WM_MOUSELEAVE:
		OnMouseLeave();
		return 0;
	}
	return CSkinWnd::OnWndMsg(msg,wp,lp);
}
void CSkinButton::OnBMSetState(WPARAM wp,LPARAM lp)
{
	Default();
	SetState( m_nButtonState,BUTTON_PRESSED,wp );
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnBMSetStyle(WPARAM wp,LPARAM lp)
{
	Default();
	SetState( m_nButtonState,BUTTON_DEFAULT,wp & BS_DEFPUSHBUTTON );
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnBMSetCheck(WPARAM wp,LPARAM lp)
{
	Default();
	SetState( m_nButtonState, BUTTON_CHECKED,( wp == BST_CHECKED ) );
	SetState( m_nButtonState, BUTTON_INDETERMINATE,( wp == BST_INDETERMINATE ) );
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}

void CSkinButton::OnMouseMove( UINT nFlags, CPoint point )
{

	if((m_nButtonState & BUTTON_HOVER) == 0 && ((nFlags & MK_LBUTTON) == 0) )
	{
		TRACKMOUSEEVENT tme;
		SetState(m_nButtonState, BUTTON_HOVER, true);
		tme.cbSize = sizeof(TRACKMOUSEEVENT);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;

		TrackMouseEvent(&tme);
	}

	if((m_CaptureState == RELEASE_IN_LEAVE))
	{
		if((nFlags & MK_LBUTTON) != 0)
		{
			::SendMessage(m_hWnd, WM_LBUTTONDOWN, m_wParamOnDown, m_lParamOnDown);
		}
		else
		{
			m_CaptureState = NO_CAPTURE_OR_UP_RELEASE;
		}
	}

	RECT rect;
	GetWindowRect(&rect);
	ClientToScreen(&point);

	if(!PtInRect(&rect, point))
	{
		//由 SetCapture 引发
		SendMessage(m_hWnd, WM_MOUSELEAVE, 0, 0);
	}



	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);

}
void CSkinButton::OnLButtonDown( UINT nFlags, const CPoint& point )
{

	SetCapture( m_hWnd );
	m_CaptureState = CAPTURE_IN_DOWN;
	m_wParamOnDown = nFlags;
	m_lParamOnDown = MAKELPARAM(point.x, point.y);


	SetFocus( m_hWnd );
	SetState( m_nButtonState, BUTTON_PRESSED, TRUE );

	Default();
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnMouseLeave()
{
	if(m_CaptureState == CAPTURE_IN_DOWN)
	{
		ReleaseCapture();
		m_CaptureState = RELEASE_IN_LEAVE;
	}

	SetState(m_nButtonState, (BUTTON_HOVER | BUTTON_PRESSED), false);
	SetState(m_nButtonState, BUTTON_NORMAL, true);

	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnSetFocus(HWND hWnd)
{
	Default();
	SetState(m_nButtonState, BUTTON_FOCUS, true);

	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnKillFocus(HWND hWnd)
{
	Default();
	SetState(m_nButtonState, BUTTON_FOCUS, false);

	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}
void CSkinButton::OnEnable(BOOL bEnable)
{
	SetState( m_nButtonState, BUTTON_DISABLED, !bEnable );
	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
    CAutoReleaseDC pDC(pWnd);
	pDC = pWnd->GetWindowDC();
	DrawButton(pDC);
}

void CSkinButton::OnLButtonUp( UINT nFlags, const CPoint& point )
{
	Default();

	ReleaseCapture();
	m_CaptureState = NO_CAPTURE_OR_UP_RELEASE;

	CWnd *pWnd = CWnd::FromHandle(m_hWnd);
	if(pWnd)
	{
        CAutoReleaseDC pDC(pWnd);
		pDC = pWnd->GetDC();
		DrawButton(pDC);
	}
}

void CSkinButton::OnPaint()
{
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	CPaintDC dc(pButton);
	DrawButton(&dc);
}

void CSkinButton::DrawButton(CDC *pDC)
{
	DWORD dwState = (LONG) SendMessage(m_hWnd, BM_GETCHECK, 0, 0);

	SetState(m_nButtonState, BUTTON_CHECKED, dwState == BST_CHECKED);
	SetState(m_nButtonState, BUTTON_INDETERMINATE, dwState == BST_INDETERMINATE);



	if(m_nButtonType == BTNTYPE_PUSHBUTTON)
		DrawPushButton(pDC);
	else if(m_nButtonType == BTNTYPE_CHECKBOX)
		DrawCheckBoxButton(pDC);
	else if(m_nButtonType == BTNTYPE_RADIOBOX)
		DrawRadioButton(pDC);
	else if(m_nButtonType == BTNTYPE_GROUPBOX)
		DrawGroupBox(pDC);
}
void CSkinButton::DrawPushButtonText(CDC *pDC,CRect rtDest)
{
	CRect rtIcon,rtText;
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	HICON hIcon = pButton->GetIcon();
	ICONINFO piconinfo;
	LONG_PTR dwStyle;
#ifdef _WIN64
	dwStyle = (DWORD)GetWindowLongPtr(m_hWnd, GWL_STYLE);
#else
	dwStyle = (DWORD)GetWindowLong(m_hWnd, GWL_STYLE);
#endif
	rtText = rtDest;
	if(m_bIcon)
	{
		GetIconInfo(hIcon,&piconinfo); //取图标信息
		rtIcon = rtDest;
		if (dwStyle & BS_TOP) //文字置顶
			rtIcon.top = rtDest.bottom - piconinfo.yHotspot*2 - 4;
		else if (dwStyle & BS_VCENTER)//文字置中
			rtIcon.top = (rtDest.bottom-rtDest.top)/2-piconinfo.yHotspot;
		else
			rtIcon.top = rtDest.top+4;

		if (dwStyle & BS_RIGHT) //文字置右
			rtIcon.left = 4;
		else if(dwStyle & BS_LEFT)//文字置左
			rtIcon.left = rtDest.right - (piconinfo.yHotspot*2 + 4);
		else
			rtIcon.left = (rtDest.right - rtDest.left)/2-piconinfo.yHotspot + 2;
		pDC->DrawIcon( rtIcon.left,rtIcon.top, hIcon);
        piconinfo.hbmColor ? DeleteObject(piconinfo.hbmColor) : NULL;
        piconinfo.hbmMask ? DeleteObject(piconinfo.hbmMask) : NULL;
	}
	else
	{
		CString strText;
		int nOldMode = pDC->SetBkMode(TRANSPARENT);
		UINT uFormat = ButtonStyle2Format(dwStyle);
		pButton->GetWindowText(strText);
		pDC->DrawText(strText,rtText,uFormat);
		pDC->SetBkMode(nOldMode);
	}
	
}
void CSkinButton::DrawPushButton(CDC *pDC)
{
	if(m_pButtonSkin == NULL)
		return;
	CRect rtWindow;
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	pButton->GetWindowRect(rtWindow);
	rtWindow.OffsetRect(-rtWindow.left,-rtWindow.top);
	CMemDC memDC(pDC,rtWindow);
	

	if (m_nButtonState & BUTTON_DISABLED)
	{
		m_pButtonSkin->DrawButton(&memDC,rtWindow,keDisabled);
	}
	else
	{
		if (m_nButtonState & BUTTON_PRESSED)
			m_pButtonSkin->DrawButton(&memDC,rtWindow,kePressed);
		else if (m_nButtonState & BUTTON_HOVER)
			m_pButtonSkin->DrawButton(&memDC,rtWindow,keHighlighted);
		else if (m_nButtonState & BUTTON_FOCUS)
			m_pButtonSkin->DrawButton(&memDC,rtWindow,keFocused);
		else if ((m_nButtonState & BUTTON_CHECKED) || (m_nButtonState & BUTTON_INDETERMINATE))
			m_pButtonSkin->DrawButton(&memDC,rtWindow,kePressed);
		else if (m_nButtonState & BUTTON_DEFAULT)
			m_pButtonSkin->DrawButton(&memDC,rtWindow,keDefault);
		else
			m_pButtonSkin->DrawButton(&memDC,rtWindow,keNormal);
	}
	CFont *pFont,*pOld;
	CFont font;
	if(m_pButtonSkin->m_bAutoFont)
	{
		pFont = pButton->GetFont(); 
		pOld = (CFont*)memDC.SelectObject( pFont );
	}
	else
	{
		font.CreateFontIndirect(&(m_pButtonSkin->m_fontButton));
		pOld = (CFont*)memDC.SelectObject( &font );
	}

	DrawPushButtonText(&memDC,rtWindow);

	memDC.SelectObject(pOld);
	if(!m_pButtonSkin->m_bAutoFont)
		font.DeleteObject();
}
void CSkinButton::DrawCheckBoxButton(CDC *pDC)
{
	if(m_pCheckSkin == NULL)
		return;
	CRect rtWindow;
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	pButton->GetWindowRect(rtWindow);
	rtWindow.OffsetRect(-rtWindow.left,-rtWindow.top);

	CMemDC memDC(pDC,rtWindow);

	int width,height;
	CRect rtCheck,rtText;
	width = m_pCheckSkin->m_stateCheckBox[keNormal].imageChecked.rtImagePos.Width();
	height = m_pCheckSkin->m_stateCheckBox[keNormal].imageChecked.rtImagePos.Height();
	rtCheck.left = rtWindow.left;
	rtCheck.right = rtCheck.left + width;
	rtCheck.top = (rtWindow.Height() - height)/2;
	rtCheck.bottom = rtCheck.top + height;

	rtText = rtWindow;
	rtText.left = rtCheck.right +2;

	m_pCheckSkin->DrawBackground(&memDC,rtWindow);

	
	if (m_nButtonState & BUTTON_DISABLED)
	{	
		if ((m_nButtonState & BUTTON_CHECKED))
			m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckDisabled,0);
		else if ((m_nButtonState & BUTTON_INDETERMINATE))
			m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckDisabled,2);
		else
			m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckDisabled,1);
	}
	else
	{
		if (m_nButtonState & BUTTON_PRESSED)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckPressed,0);
			else if ((m_nButtonState & BUTTON_INDETERMINATE))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckPressed,2);
			else
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckPressed,1);
		}
		else if (m_nButtonState & BUTTON_HOVER)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckHover,0);
			else if ((m_nButtonState & BUTTON_INDETERMINATE))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckHover,2);
			else
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckHover,1);
		}
		else if (m_nButtonState & BUTTON_FOCUS)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckFocused,0);
			else if ((m_nButtonState & BUTTON_INDETERMINATE))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckFocused,2);
			else
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckFocused,1);
		}
		else
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckNormal,0);
			else if ((m_nButtonState & BUTTON_INDETERMINATE))
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckNormal,2);
			else
				m_pCheckSkin->DrawBox(&memDC,rtCheck,keCheckNormal,1);
		}
	}
	CFont *pFont = NULL;
	CFont *pOld = NULL;
	CFont font;
	if(m_pCheckSkin->m_bAutoFont)
	{
		pFont = pButton->GetFont(); 
		pOld = (CFont*)memDC.SelectObject( pFont );
	}
	else
	{
		font.CreateFontIndirect(&(m_pCheckSkin->m_fontCheckBox));
		pOld = (CFont*)memDC.SelectObject( &font );
	}
	DrawPushButtonText(&memDC,rtText);

	memDC.SelectObject(pOld);
	if(!m_pCheckSkin->m_bAutoFont)
		font.DeleteObject();

}
void CSkinButton::DrawRadioButton(CDC *pDC)
{
	if(!m_pRadioSkin)
		return;
	CRect rtWindow;
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	pButton->GetWindowRect(rtWindow);
	rtWindow.OffsetRect(-rtWindow.left,-rtWindow.top);

	CMemDC memDC(pDC,rtWindow);

	int width,height;
	CRect rtRadio,rtText;
	width = m_pRadioSkin->m_stateRadio[keNormal].imageChecked.rtImagePos.Width();
	height = m_pRadioSkin->m_stateRadio[keNormal].imageChecked.rtImagePos.Height();
	rtRadio.left = rtWindow.left;
	rtRadio.right = rtRadio.left + width;
	rtRadio.top = (rtWindow.Height() - height)/2;
	rtRadio.bottom = rtRadio.top + height;

	rtText = rtWindow;
	rtText.left = rtRadio.right+2;

	m_pRadioSkin->DrawBackground(&memDC,rtWindow);

	int nOldMode = pDC->SetBkMode(TRANSPARENT);
	if (m_nButtonState & BUTTON_DISABLED)
	{	
		if ((m_nButtonState & BUTTON_CHECKED))
			m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioDisabled,0);
		else
			m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioDisabled,1);
	}
	else
	{
		if (m_nButtonState & BUTTON_PRESSED)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioPressed,0);
			else
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioPressed,1);
		}
		else if (m_nButtonState & BUTTON_HOVER)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioHover,0);
			else
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioHover,1);
		}
		else if (m_nButtonState & BUTTON_FOCUS)
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioFocused,0);
			else
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioFocused,1);
		}
		else
		{
			if ((m_nButtonState & BUTTON_CHECKED))
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioNormal,0);
			else
				m_pRadioSkin->DrawBox(&memDC,rtRadio,keRadioNormal,1);
		}
	}

	CFont *pFont = NULL;
	CFont *pOld = NULL;
	CFont font;
	if(m_pRadioSkin->m_bAutoFont)
	{
		pFont = pButton->GetFont(); 
		pOld = (CFont*)memDC.SelectObject( pFont );
	}
	else
	{
		
		font.CreateFontIndirect(&(m_pRadioSkin->m_fontRadio));
		pOld = (CFont*)memDC.SelectObject( &font);
	}
	DrawPushButtonText(&memDC,rtText);
	memDC.SelectObject(pOld);
	if(!m_pRadioSkin->m_bAutoFont)
		font.DeleteObject();
	memDC.SetBkMode(nOldMode);
}
void CSkinButton::DrawGroupBox(CDC *pDC)
{
	if(m_pGroupSkin == NULL)
		return;
	CRect rtWindow;
	CButton *pButton = (CButton*)CWnd::FromHandle(m_hWnd);
	pButton->GetWindowRect(rtWindow);
	rtWindow.OffsetRect(-rtWindow.left,-rtWindow.top);

//	CMemDC memDC(pDC,rtWindow);
	CString strCaption;
	pButton->GetWindowText(strCaption);
	CFont *pFont,*pOld;
	CFont font;
	if(m_pGroupSkin->m_bAutoFont)
	{
		pFont = pButton->GetFont(); 
		pOld = (CFont*)pDC->SelectObject( pFont );
	}
	else
	{
		
		font.CreateFontIndirect(&(m_pGroupSkin->m_fontGroupBox));
		pOld = (CFont*)pDC->SelectObject( &font );
	}
	
	CSize size =  pDC->GetTextExtent( strCaption );

	rtWindow.top += size.cy/2 ;
	m_pGroupSkin->DrawFrame(pDC,rtWindow);
	CRect rtCaption;
	rtCaption.left = 5;
	rtCaption.right = rtCaption.left + size.cx + 5;
	rtCaption.top = 0;
	rtCaption.bottom = rtCaption.top + size.cy+2;
	m_pGroupSkin->DrawCaption(pDC,rtCaption);

	
	int oldMode = pDC->SetBkMode(TRANSPARENT);
	rtCaption.left += 2;
	pDC->DrawText(strCaption,rtCaption,DT_LEFT|DT_VCENTER|DT_SINGLELINE);

	pDC->SetBkMode(oldMode);
	pDC->SelectObject(pOld);
	if(!m_pGroupSkin->m_bAutoFont)
		font.DeleteObject();

}